perm filename SERVO.FAI[CMS,LCS]6 blob sn#426288 filedate 1979-03-20 generic text, type T, neo UTF8
00100		TITLE SERVO
00200		.INSERT ASMBL.FAI[CMS,LCS]
00300	
00400	;If HSTTMR or CKWORD or ? then stop?
00500	;Check notebook and add stop? etc.
00600	;Check GPOSER and in servo formula for sign reverse?
00700	
00800	;I/O address definitions.
00900	   DAC ← 100000	;8 bit DAC.
01000	   JCR ← 120000	;Joint control output register.
01100	   ENCL ← 140000	;Encoder mux low.
01200	   ENCH ← 140001	;Encoder mux high.
01300	
01400	   STKSIZ ← 377	;Stack size.
01500	   LSBENB ← 40	;Enable LSB servo.
01600	
01700	;Zero page variables.
01800	;Not shared.
01900	
02000	DSPAT:	BLOCK 2	;Dispatch address for commands.
02100	DEFCMD:	0	;Deferred command.
02200	SAVPOS:	BLOCK 2	;Position for deferred servo command.
02300	
02400	CMDVEL:	BLOCK 2	;Commanded velocity.
02500	CURVEL:	BLOCK 2	;Current velocity.
02600		0	;SETPT-1.
02700	SETPT:	BLOCK 2	;Current setpoint.
02800		0	;SETINC-1.
02900	SETINC:	BLOCK 2	;Interpolating increment for setpoints.
03000	OLDSP:	BLOCK 2	;Last commanded setpoint, for CMDVEL.
03100	POSERR:	BLOCK 2	;Current position error.
03200	DACSIG:	BLOCK 2	;Scratch.
03300	
03400	INCTR:	0	;Count the interpolations.
03500	HSTTMR:	0	;Count ticks between host commands.
03600	
03700	LOGTMP:	BLOCK 4	;Temp for the arithmetic routines.
03800	
03900	ZAPEND ← .-1	;Clear all the above in startup.
04000	
04100	CURPOS:	BLOCK 2	;Current position, extended to 2 bytes.
04200	
04300	TL:	0	;Scratch for grey to binary.
04400	TH:	0
04500	
04600	FTMP:	BLOCK 2	;Copy of friction coefficient for multiply.
     

00100	;Shared ram.
00200	   LOC 200	;Second half of zero page.
00300	
00400		0	;Locked.
00500	STATUS:	0	;Flags for the host.
00600	
00700		0	;Locked.
00800	MODE:	0	;Mode bits from host.
00900	
01000	CKWORD:	BLOCK 2	;Host I/O check/command word.
01100	CMDPOS:	BLOCK 2	;Commanded position from host.
01200	
01300		0	;Locked.
01400	IOCTRL:	0	;Copy of JCR output port.
01500	
01600	;NINTER = function of INTSCL?
01700		0	;Locked.
01800	NINTER:	0	;# of interpolations between position
01900			;commands.
02000		0	;Locked.
02100	INTSCL:	0	;# of bits to shift setpoint dif for
02200			;interpolating.
02300		0	;Locked.
02400	HSTLIM:	0	;# of clock ticks allowed between host
02500			;commands.
02600	FRICTN:	BLOCK 2	;Viscous damping coefficient.
02700	GRAVTY:	BLOCK 2	;DC offset for gravity.
02800	POSTOL:	BLOCK 2	;Half-width of position tolerance band.
02900	INTTOL:	BLOCK 2	;Half-width of integration band.
03000	
03100	
03200	;Start of prom.
03300	   LOC 174000
03400	
03500	INITBL:	STATUS	↔	200
03600		MODE	↔	0
03700	
03800		NINTER	↔	=32
03900		INTSCL	↔	5
04000	
04100		HSTLIM	↔	=48
04200	
04300		377	;End of INITBL flag.
     

00100	;Power on and restart reset.
00200	START:	CLD
00300		LDXI	STKSIZ	;Setup stack.
00400		TXS
00500	
00600		LDAI	0
00700		LDXI	ZAPEND
00800	RLOOP:	STAZX	0	;Reset ram.
00900		DEX
01000		BPL	RLOOP
01100		STA	DAC	;Clear DAC.
01200	
01300		LDXI	370	;-8.
01400	ZSR:	STAZX	FRICTN+10	;Clear shared ram.
01500		INX
01600		BMI	ZSR
01700	
01800		TAY
01900		BEQ	RSTDEF	;Jump
02000	
02100	
02200	DLOOP:	INY
02300		LDAY	INITBL	;Init ram.
02400		STAZX	0
02500		INY
02600	
02700	RSTDEF:	LDXY	INITBL
02800		CPXI	377
02900		BNE	DLOOP
03000	
03100	STOP:	SEI	;Disable interrupts and stop?
03200		JSR	GETPOS	;Read encoder and convert to binary.
03300	
03400		JSR	SETPOS	;Set position and stop.
03500	
03600		CLI	;End of reset.
     

00100	RSTCKW:	LDAI	0	;Reset check word.
00200		SEI
00300		STAZ	CKWORD
00400		STAZ	CKWORD+1
00500		CLI
00600	;Idle loop. Wait for command.
00700	IDLE:	LDAZ	CKWORD+1;Check for new check word.
00800		BEQ	IDLE	;Not equal if bit 7 is 2's comp. of low byte?
00900	
01000		CLC
01100		SEI
01200		ADCZ	CKWORD
01300		LDXZ	CKWORD+1
01400		CLI
01500		TAY
01600		BNE	STOP	;Check word error.
01700	   ;Check here for immediate or deferred.
01800		LDAZ	DEFCMD	;Check if no TICK?
01900		BNE	STOP
02000	
02100		SEI
02200		LDAZ	CMDPOS	;Read position for servo command.
02300		LDYZ	CMDPOS+1
02400		CLI
02500	
02600		STAZ	SAVPOS	;Save it for later.
02700		STYZ	SAVPOS+1
02800	
02900		STXZ	DEFCMD	;Save deferred command.
03000	
03100		BNE	RSTCKW	;Done. Jump and handshake with CKWORD.
     

00100	;Clock tick interrupt.
00200	TICK:	PHA	;Save state.
00300		TXA
00400		PHA
00500		TYA
00600		PHA
00700	
00800		JSR	GETPOS	;Read position and convert to binary.
00900	
01000		TAY	;Save low byte of binary position.
01100		LDXZ	TH	;Get high byte.
01200		SEC
01300		SBCZ	CURPOS	;Subtract the old position
01400		STAZ	CURVEL	;yielding the velocity.
01500		TXA	;High byte of binary position.
01600		SBCZ	CURPOS+1
01700		STAZ	CURVEL
01800	
01900		STYZ	CURPOS	;Set the current position.
02000		STXZ	CURPOS+1
02100		DECZ	HSTTMR	;Count the ticks since the last command
02200		BPL	HOSTOK	;and check for timeout.
02300	
02400		LDAI	0	;Host dead. Stop.
02500		STAZ	HSTTMR
02600		STAZ	CMDVEL
02700		STAZ	CMDVEL+1
02800	
02900	HOSTOK:	LDAI	4
03000		BITZ	IOCTRL	;If position mode is off,
03100		BNE	INTRS
03200		JMP	CURSRV	;don't servo.
03300	
03400	;Interpolate the setpoints.
03500	INTRS:	CLC
03600		LDAZ	SETPT-1
03700		ADCZ	SETINC-1;Add the increment to the setpoint.
03800		STAZ	SETPT-1
03900		LDAZ	SETPT
04000		ADCZ	SETINC
04100		STAZ	SETPT
04200		LDAZ	SETPT+1
04300		ADCZ	SETINC+1
04400		STAZ	SETPT+1
04500	
04600		DECZ	INCTR	;Check if this is the last interpolation.
04700		BNE	GPOSER
04800	
04900		LDAI	0	;Clear SETINC if done interpolating.
05000		STAZ	SETINC-1
05100		STAZ	SETINC
05200		STAZ	SETINC+1
05300	
05400	;Calculate the position error.
05500	GPOSER:	SEC
05600		LDAZ	CURPOS	;POSERR ← CURPOS - SETPT.
05700		SBCZ	SETPT
05800		STAZ	POSERR
05900		LDAZ	CURPOS+1
06000		SBCZ	SETPT+1
06100		STAZ	POSERR+1
     

00100		BITZ	MODE	;If servo is disabled, we're
00200		BPL	OOTOL	;automatically out of tolerance
00300	
00400		LDAZ	POSERR+1;Test the sign of pos error.
00500		BMI	NEGPER
00600	
00700		SEI
00800		LDAZ	POSTOL	;Positive. Compare with tol.
00900		CMPZ	POSERR
01000		LDAZ	POSTOL+1
01100		CLI
01200		SBCZ	POSERR+1
01300		BCS	TOLOK	;In tolerance.
01400		BCC	OOTOL	;Jump.
01500	
01600	NEGPER:	CLC	;Negative. Add the tolerance.
01700		SEI
01800		LDAZ	POSTOL
01900		ADCZ	POSERR
02000		LDAZ	POSTOL+1
02100		CLI
02200		ADCZ	POSERR+1
02300		BCS	TOLOK	;In tolerance.
02400	
02500	OOTOL:	LDAZ	IOCTRL	;Out of tolerance.
02600		ANDI	177	;Turn off the in tolerance
02700		BNE	WCNTRL	;indicator.
02800	
02900	TOLOK:	LDAZ	IOCTRL	;In tolerance. Turn it on.
03000		ORAI	200
03100	WCNTRL:	STAZ	IOCTRL
03200		STA	JCR	;Copy it to output.
03300	
03400	;Delete from here to end of page if no integrator?
03500		BITZ	MODE	;If intergration is disabled,
03600		BVC	OOBAND	;turn it off.
03700		LDAZ	POSERR+1;Test sign of position error.
03800		BMI	ADTOL
03900	
04000		SEI
04100		LDAZ	INTTOL	;Positive. Compare with tol.
04200		CMPZ	POSERR
04300		LDAZ	INTTOL+1
04400		CLI
04500		SBCZ	POSERR+1
04600		BCS	INBAND	;In band. Turn on integrator.
04700		BCC	OOBAND	;Jump.
04800	
04900	ADTOL:	CLC	;Negative. Add the tolerance.
05000		SEI
05100		LDAZ	INTTOL
05200		ADCZ	POSERR
05300		LDAZ	INTTOL+1
05400		CLI
05500		ADCZ	POSERR+1
05600		BCS	INBAND	;Check if in band.
05700	
05800	OOBAND:	LDAZ	IOCTRL	;Out of band. Turn off
05900		ORAI	10	;integration by setting the
06000		ANDI	357	;control bit. LSB servo off.
06100		BNE	WCTRL2	;Jump.
     

00100	;Delete from here to WCTRL2 if no LSB servo?
00200	INBAND:	LDAI	LSBENB	;In band. Is LSB servo enabled?
00300		BITZ	MODE
00400		BEQ	RCNTRL
00500	
00600		LDAZ	POSERR	;Yes. Is the error exactly 0?
00700		ORAZ	POSERR+1
00800		BNE	RCNTRL
00900	
01000		LDAZ	IOCTRL	;It is. Integration off, LSB
01100		ORAI	30	;servo on.
01200		BNE	WCTRL2	;Jump.
01300	
01400	RCNTRL:	LDAZ	IOCTRL	;LSB disabled or error
01500		ANDI	347	;not zero. LSB servo off,
01600				;integration on.
01700	
01800	WCTRL2:	STAZ	IOCTRL
01900		STA	JCR	;Output it.
02000	
02100		LDYZ	CURVEL	;Get the velocity,
02200		LDAZ	CURVEL+1
02300		JSR	LOG
02400	
02500		SEI
02600		LDXZ	FRICTN	;(Copy friction for multiply.)
02700		STXZ	FTMP
02800		LDXZ	FRICTN+1
02900		CLI
03000		STXZ	FTMP+1
03100		LDXI	FTMP	;multiply by the friction
03200		JSR	MULTIP	;coefficient,
03300		JSR	EXP
03400	
03500		TAX	;Save high byte.
03600		TYA	;Get low byte.
03700		CLC	;add the position error...
03800		ADCZ	POSERR
03900		STAZ	DACSIG
04000		TXA
04100		ADCZ	POSERR+1
04200		STAZ	DACSIG+1
04300	
04400		CLC	;...and the gravity offset.
04500		LDAZ	DACSIG
04600		SEI
04700		ADCZ	GRAVTY
04800		TAY	;Save low byte.
04900		LDAZ	GRAVTY+1
05000		CLI
05100		ADCZ	DACSIG+1
05200	
05300		JSR	PUTDAC	;Put result out to the DAC.
     

00100	CMDSP:	LDAZ	DEFCMD	;Check for a command.
00200		BEQ	INTXIT
00300	
00400		ANDI	2	;Low nibble command bit.
00500		TAX
00600		LDAX	CMDTBL	;Get command address.
00700		STAZ	DSPAT
00800		LDAX	CMDTBL+1
00900		STAZ	DSPAT+1
01000	
01100		JMPIN	DSPAT	;Execute command.
01200	
01300	CMDEND:	LDAI	0	;Done with deferred command.
01400		STAZ	DEFCMD	;Reset command word.
01500	
01600	INTXIT:	PLA	;Restore state and dismiss interrupt.
01700		TAY
01800		PLA
01900		TAX
02000		PLA
02100		RTI
02200	
02300	CURSRV:	LDAI	0	;Not servoing ("Current mode")...
02400		STAZ	SETPT-1	;Make the setpoint track
02500		LDAZ	CURPOS	;the current position in order to
02600		STAZ	SETPT	;keep the arm from twitching when
02700		LDAZ	CURPOS+1;the host enables the servo.
02800		STAZ	SETPT+1
02900		JMP	CMDSP	;Go check on commands.
03000	
03100	CMDTBL:		;DEFERRED COMMAND TABLE.
03200		CMDEND∧377	;Nop.
03300		(CMDEND⊗-10)∧377
03400	
03500		CMDSRV∧377	;Servo command.
03600		(CMDSRV⊗-10)∧377
     

00100	;Deferred commands.
00200	;Put this routine on page 10-2.
00300	CMDSRV:	LDAZ	MODE	;Servo command.
00400		ANDI	202	;Test for servo enabled.
00500		CMPI	200
00600		BEQ	ENBLD
00700		JMP	CMDEND	;No. End this command. 
00800	
00900	ENBLD:	LDAZ	SAVPOS	;Enabled.
01000		LDXZ	SAVPOS+1;Get position.
01100		STAZ	DACSIG
01200		STXZ	DACSIG+1
01300		SEC
01400		SBCZ	SETPT
01500		STAZ	SETINC
01600		TXA
01700		SBCZ	SETPT+1
01800		LDXI	0
01900		STXZ	SETPT-1
02000		STXZ	SETINC-1
02100		LDXZ	INTSCL
02200	
02300	SCAL:	CMPI	200	;Extend sign.
02400		RORA
02500		RORZ	SETINC
02600		RORZ	SETINC-1
02700		DEX
02800		BNE	SCAL
02900	
03000		STAZ	SETINC+1
03100		LDAZ	NINTER
03200		STAZ	INCTR
03300		SEC
03400		LDAZ	DACSIG
03500		SBCZ	OLDSP
03600		STAZ	CMDVEL
03700		LDAZ	DACSIG+1
03800		SBCZ	OLDSP+1
03900		STAZ	CMDVEL+1
04000		LDAZ	DACSIG
04100		STAZ	OLDSP
04200		LDAZ	DACSIG+1
04300		STAZ	OLDSP+1
04400	
04500		LDAZ	IOCTRL
04600		ORAI	44	;Turn on servo and current mode enable bits.
04700		STAZ	IOCTRL
04800		STA	JCR	;Output it.
04900		LDAZ	HSTLIM	;Reset host timer.
05000		STAZ	HSTTMR
05100		JMP	CMDEND
     

00100	;Position conversion routine.
00200	;Put this routine on page 10-3.
00300	GETPOS:	LDY	ENCL	;Read encoder.
00400		LDA	ENCH
00500	
00600	;Convert from grey to binary.
00700		STAZ	TH
00800		LSRA	;Shift by 1.
00900		EORZ	TH
01000		STAZ	TH
01100		TAX	;X ← high byte.
01200	
01300		TYA
01400		STAZ	TL
01500		RORA
01600		EORZ	TL
01700		STAZ	TL
01800	
01900		LSRZ	TH	;Shift by 2.
02000		RORA
02100		LSRZ	TH
02200		RORA
02300	
02400		EORZ	TL
02500		STAZ	TL
02600		TAY	;Y ← low byte.
02700		TXA
02800		EORZ	TH
02900		STAZ	TH
03000	
03100		LSRA	;Shift by 4.
03200		RORZ	TL
03300		LSRA
03400		RORZ	TL
03500		LSRA
03600		RORZ	TL
03700		LSRA
03800		RORZ	TL
03900	
04000		EORZ	TH
04100		STAZ	TH
04200		TYA
04300		EORZ	TL
04400		EORZ	TH	;Shift by 8.
04500	;Returns converted position in A (low) and TH (high).
04600		RTS
     

00100	;Not a subroutine? Put this routine on page 3-1?
00200	;Set position subroutine.
00300	;Enter with position in A (low) and X (high).
00400	;Sets current position to that value, puts the setpoint
00500	;to the same, clears the setpoint interpolating
00600	;increment, and goes into stop mode?
00700	SETPOS:	STAZ	CURPOS	;Set the current position.
00800		STXZ	CURPOS+1
00900	
01000		STAZ	SETPT	;Set the position command.
01100		STXZ	SETPT+1
01200		STAZ	OLDSP
01300		STXZ	OLDSP+1
01400	
01500		LDAI	75	;I/O control bits for servo
01600		STAZ	IOCTRL	;enable on, all others off.
01700		STA	JCR
01800	
01900		LDAI	0
02000		STAZ	SETPT-1	;Clear the setpoint extension,
02100		STAZ	SETINC-1;the interpolator,
02200		STAZ	SETINC
02300		STAZ	SETINC+1
02400		STAZ	CMDVEL	;and the commanded velocity.
02500		STAZ	CMDVEL+1
02600	
02700		LDAZ	SETPT	;Return the regs. unchanged.
02800		RTS
02900	
03000	;DAC output subroutine.
03100	;Enter with 2 byte value in Y (low), A (high).
03200	;Clobbers all registers, but the 8 bits the
03300	;DAC got are returned in A.
03400	PUTDAC:	BMI	NEGDAC	;Assuming the last inst. loaded A.
03500		CPYI	200	;Positive. Compare with 2↑7.
03600		SBCI	0
03700		BCC	INRNGE
03800	
03900	TOOHI:	LDYI	177	;Too high. Saturate positive.
04000		BNE	INRNGE	;Jump.
04100	
04200	NEGDAC:	CPYI	200	;Negative. Compare with -2↑7.
04300		SBCI	377
04400		BCS	INRNGE
04500	
04600	TOOLOW:	LDYI	200	;Too low. Saturate to -2↑7.
04700	
04800	INRNGE:	LDAY	VETBL	;Straighting it.
04900		STA	DAC	;Output 8 bits to the DAC.
05000		RTS
     

00100	;Arithmetic routines.
00200	;Enter with high byte in A, low in Y.
00300	;Returns A = characteristic and sign, Y = mantissa.
00400	;Clobbers X, LOGTMP, LOGTMP+1.
00500	LOG:	STYZ	LOGTMP	;Save the inputs.
00600		STAZ	LOGTMP+1
00700	
00800		LDXI	20+100	;?Init characteristic to 15.
00900		CMPI	0	;Test sign of input.
01000		BPL	POSIN
01100		SEC	;Negative. 2's complement it.
01200		LDAI	0
01300		SBCZ	LOGTMP
01400		STAZ	LOGTMP
01500		LDAI	0
01600		SBCZ	LOGTMP+1
01700	POSIN:	BNE	NORML	;Is high byte zero?
01800		LDAZ	LOGTMP	;Yes. Low byte?
01900		BEQ	RTRN	;If so, return zero.
02000		LDYI	0	;Low nonzero. Shift left one
02100		STYZ	LOGTMP	;byte,
02200		LDXI	10+100	;change characteristic to 7.
02300	NORML:	DEX	;Normalize the number, counting the
02400		ASLZ	LOGTMP	;characteristic down. When the
02500		ROLA	;first "1" shifts out, we've subtracted
02600		BCC	NORML	;1 from the normalized number
02700		ASLZ	LOGTMP	;(This rounds the result)
02800		ADCI	=11	;and are left with the fraction
02900		TAY	;Adding 11 to that is equivalent to
03000		TXA	;adding 0.043.
03100		ADCI	0	;Propagate the carry into the
03200				;characteristic.
03300		ASLA	;Insert the sign bit from the saved
03400		ASLZ	LOGTMP+1;input.
03500		RORA
03600	RTRN:	RTS	;Done.
03700	
03800	;Enter with sign and characteristic in A, mantissa in Y
03900	;Returns 16-bit integer, low byte in Y, high in A.
04000	;Clobbers X, LOGTMP, LOGTMP+1.
04100	EXP:	STAZ	LOGTMP+1;Save sign of input.
04200		ANDI	177	;Mask it off.
04300		BEQ	ZEROIN	;Zero characteristic returns
04400		TAX	;zero.
04500		TYA	;Get the mantissa...
04600		SEC
04700		SBCI	=11	;...subtract 0.043...
04800		STAZ	LOGTMP	;(save this value)
04900		TXA	;...propagate the carry and get rid
05000		SBCI	100	;of the XS-64 offset.
05100		BMI	NEGIN	;If negative (value < 1.0)
05200				;return zero.
05300		CMPI	=15	;Test for overflow (value>=2↑15
05400		BCS	SATUR
05500		TAX	;...no. Number is in range.
05600		ADCI	370	;Is characteristic below 8?
05700		BMI	BLOATE
05800		TAX	;No. Reduce if by 8,
05900		JSR	UNNORM	;unnormalize.
06000		BMI	GETTMP	;Jump.
     

00100	BLOATE:	JSR	UNNORM	;Yes. Unnormalize, then
00200		ASLZ	LOGTMP	;(round result)
00300		ADCI	0
00400		STAZ	LOGTMP	;use result as low byte and
00500		LDAI	0	;set high byte to zero.
00600	
00700	GETTMP:	LDYZ	LOGTMP
00800	GTMP1:	LDXZ	LOGTMP+1;Test sign of input...
00900		BPL	POSIGN
01000		STAZ	LOGTMP+1;...negative. 2's complement
01100		LDAI	0	;the result.
01200		SEC
01300		SBCZ	LOGTMP
01400		TAY
01500		LDAI	0
01600		SBCZ	LOGTMP+1
01700	POSIGN:	RTS
01800	
01900	NEGIN:	LDAI	0	;Set the result to zero if the
02000	ZEROIN:	TAY	;input is negative.
02100		RTS
02200	
02300	SATUR:	LDYI	377	;Saturate result to 2↑15 - 1 if
02400		STYZ	LOGTMP	;input was 15 or more.
02500		LDAI	177
02600		BNE	GTMP1	;Jump.
02700	
02800	UNNORM:	LDAI	1	;Unnormalize subroutine. Add 1
02900		BNE	DECRX	;to the fraction.
03000	
03100	SCALE:	ASLZ	LOGTMP	;Scale the fraction left by the
03200		ROLA	;amount of the characteristic.
03300	DECRX:	DEX
03400		BPL	SCALE
03500		RTS
03600	
03700	;Enter with characteristic of multiplier in A,
03800	;mantissa in Y, X pointing to a pair of base page
03900	;locations containing the multiplicand (mantissa in the
04000	;low byte).
04100	;Returns the product in A and Y, same form as the
04200	;multiplier. Leaves X unchanged. Clobbers LOGTMP and
04300	;LOGTMP+1.
04400	MULTIP:	PHA
04500		EORZX	1	;Compute sign of result,
04600		STAZ	LOGTMP+1	;save it away.
04700		PLA
04800		ANDI	177	;Mask off multiplier sign.
04900		BEQ	ZEROIN	;If zero, return zero.
05000		STAZ	LOGTMP
05100		TYA	;Add the two logarithms.
05200		CLC
05300		ADCZX	0
05400		TAY
05500		LDAZX	1
05600		ANDI	177	;If multiplicand is zero,
05700		BEQ	ZEROIN	;return a zero.
05800		ADCZ	LOGTMP
05900		SEC
06000		SBCI	100	;Correct the XS-64 offset.
     

00100		BPL	INSIGN	;Result in range?
00200		ANDI	100	;No. If underflow,
00300		BNE	NEGIN	;return zero.
00400		LDAI	177	;Overflow. Saturate to
00500		LDYI	377	;highest magnitude.
00600	
00700	INSIGN:	ASLA	;Insert the sign of the result.
00800		ASLZ	LOGTMP+1
00900		RORA
01000		RTS
01100	
01200	;Inverse function: 2's complement the magnitude part
01300	;of a 15-bit logarithm.
01400	;Enter with characteristic in A, mantissa in Y.
01500	;Returns inverse in the same form. X unchanged.
01600	;Clobbers LOGTMP and LOGTMP+1.
01700	INV:	STYZ	LOGTMP	;Pretty straightforward...
01800		STAZ	LOGTMP+1
01900		SEC
02000		LDAI	0	;Complement the number by
02100		SBCZ	LOGTMP	;subtracting it from zero.
02200		TAY
02300		LDAI	0
02400		SBCZ	LOGTMP+1
02500		JMP	INSIGN	;Insert the original sign.
02600	
02700	;DAC output table.
02800	   LOC (.∨377)+1	;For start of next page.
02900	VETBL:		;DAC output table.
03000	N ← 0
03100	REPEATE 256,{N ↔ N←N+1 ↔}
03200	
03300	   NMI ← START	;Reset??
03400	;Interrupt vectors.
03500	   LOC 177772
03600		NMI∧377
03700		(NMI⊗-10)∧377
03800		START∧377
03900		(START⊗-10)∧377
04000		TICK∧377
04100		(TICK⊗-10)∧377
04200	END